package user

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/silenceper/wechat/v2/miniprogram/auth"
	"github.com/silenceper/wechat/v2/util"
	"time"
	"wx-uniapp-go/internal/domain/errcode"
	"wx-uniapp-go/internal/enums"
	"wx-uniapp-go/internal/logic/token_logic"
	"wx-uniapp-go/internal/repository/dto"
	"wx-uniapp-go/internal/repository/models"
	"wx-uniapp-go/internal/server/echo"
	"wx-uniapp-go/third_party/oss"
	"wx-uniapp-go/third_party/rediscli"
	"wx-uniapp-go/utils"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

func UserLogin(c *gin.Context) {
	ctx := echo.TraceCtx(c)
	req := new(dto.LoginReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		echo.Fail(c).Error(errcode.ParametersErr)
		return
	}

	loginRsp := new(dto.LoginRsp)
	switch req.LoginType {
	case "mp":

		result, err := WxLogin(ctx, req.Code)
		if err != nil {
			echo.Fail(c).Error(err)
			return
		}

		// 查找或创建用户
		user, err := models.GetUserByOpenId(ctx, result.OpenID)
		if err != nil {
			echo.Fail(c).Error(err)
			return
		}

		if user == nil || user.Id == 0 {
			// 用户不存在，返回错误，引导去注册
			echo.Fail(c).Error(errcode.UserNotExist)
			return
		}

		// 生成登录token
		appToken, expireTime, err := token_logic.NewTokenClient(ctx).CreateCommonToken("KUAISONG", user.Id)
		if err != nil {
			echo.Fail(c).Error(err)
			return
		}

		loginRsp = &dto.LoginRsp{
			Token:  appToken,
			Expire: expireTime,
			UserInfo: &dto.UserInfo{
				UniqueId: user.UniqueId,
				Nickname: user.Nickname,
				// ... 其他用户信息
			},
		}

	case "official":
		// 公众号登录逻辑
	case "app":
		// APP登录逻辑
	}

	echo.Success(c, loginRsp)
	return
}

// UserRegister 用户注册
func UserRegister(c *gin.Context) {
	ctx := echo.TraceCtx(c)
	req := new(dto.LoginReq)
	if err := c.ShouldBindJSON(&req); err != nil {
		echo.Fail(c).Error(errcode.ParametersErr)
		return
	}

	result, err := WxLogin(ctx, req.Code)
	if err != nil {
		echo.Fail(c).Error(err)
		return
	}
	loginRsp := new(dto.LoginRsp)
	user, err := models.GetUserByOpenId(ctx, result.OpenID)
	if err != nil {
		echo.Fail(c).Error(err)
		return
	}
	if user == nil || user.Id == 0 {
		_, inviteCode, _ := utils.ShortCode(5, 6)
		inviteUserId := int64(0)
		if req.Code != "" {
			inviteUser, _ := models.UserGetOneByCode(ctx, req.Code)
			if inviteUser != nil {
				inviteUserId = inviteUser.Id
			}
		}
		now := time.Now()
		user = &models.User{
			Avatar:        oss.Cli.JoinPath("/default/83025aafa40f4bfb8ad9c4ca114f78f0f7361826.png"),
			Nickname:      "uniapp_" + utils.GetShortUUID(),
			OpenId:        result.OpenID,
			UnionId:       result.OpenID,
			UniqueId:      uuid.New().String(),
			Mobile:        req.Mobile,
			Status:        1,
			RegIp:         c.ClientIP(),
			RegFrom:       req.LoginType,
			LastLoginIp:   c.ClientIP(),
			RegTime:       now,
			LastLoginTime: now,
			UpdateTime:    now,
			InviteCode:    inviteCode,
			InviteUser:    inviteUserId,
		}
		_, err = models.Insert(ctx, user)
		if err != nil {
			echo.Fail(c).Error(err)
			return
		}

	}

	appToken, expireTime, err := token_logic.NewTokenClient(ctx).CreateCommonToken("", user.Id)
	if err != nil {
		echo.Fail(c).Error(err)
		return
	}
	loginRsp = &dto.LoginRsp{
		Token:  appToken,
		Expire: expireTime,
		UserInfo: &dto.UserInfo{
			UniqueId: user.UniqueId,
			Nickname: user.Nickname,
			Avatar:   oss.Cli.JoinPath(user.Avatar),
			Mobile:   utils.EncryptPhoneNumber(user.Mobile),
		},
	}

	echo.Success(c, loginRsp)
	return
}

func WxLogin(ctx context.Context, code string) (result auth.ResCode2Session, err error) {
	sessionStr, err := rediscli.Default().Get(ctx, fmt.Sprintf(enums.UserCode2Session, code))
	if err != nil {
		return
	}
	result = auth.ResCode2Session{}
	if sessionStr != "" {
		_ = json.Unmarshal([]byte(sessionStr), &result)
	} else {
		//// 初始化微信小程序配置
		//wc := wechat.NewWechat()
		//memory := cache.NewMemory()
		//cfg := &config.Config{
		//	AppID:     viper.GetString("wechat:mini:appid"),     // 从配置文件获取
		//	AppSecret: viper.GetString("wechat:mini:appsecret"), // 从配置文件获取
		//	Cache:     memory,
		//}
		//mini := wc.GetMiniProgram(cfg)
		//// 登录凭证校验
		//result, err = mini.GetAuth().Code2Session(code)
		//if err != nil {
		//	return
		//}
		result = auth.ResCode2Session{
			CommonError: util.CommonError{},
			OpenID:      utils.GetShortUUID(),
			SessionKey:  utils.GetShortUUID(),
			UnionID:     utils.GetShortUUID(),
		}

		err = rediscli.Default().SetBytes(ctx, fmt.Sprintf(enums.UserCode2Session, code), result, 24*time.Hour)
		if err != nil {
			return
		}
	}
	return
}
